package com.tsd.jxc.buy.service.impl;

import com.tsd.base.service.BaseCodeRuleService;
import com.tsd.base.service.BaseInvoiceInfoService;
import com.tsd.common.vo.BatchDeleteLogicVo;
import com.tsd.core.annotation.GenSnQue;
import com.tsd.core.constants.Constants;
import com.tsd.core.constants.VersionConstants;
import com.tsd.core.datasource.DataSourceContextHolder;
import com.tsd.core.service.GetDuplicatedObj;
import com.tsd.core.thread.ThreadPoolTaskUtil;
import com.tsd.core.utils.DoubleUtil;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.ListUtil;
import com.tsd.core.vo.HlpException;
import com.tsd.core.vo.PageBean;
import com.tsd.jxc.buy.dao.JxcBuyOrderDetailMapper;
import com.tsd.jxc.buy.dao.JxcBuyOrderDetailSodMapper;
import com.tsd.jxc.buy.dao.JxcBuyOrderMapper;
import com.tsd.jxc.buy.entity.JxcBuyOrder;
import com.tsd.jxc.buy.entity.JxcBuyOrderDetailExt;
import com.tsd.jxc.buy.entity.JxcBuyOrderExt;
import com.tsd.jxc.buy.entity.JxcBuyReturnBillExt;
import com.tsd.jxc.buy.service.JxcBuyOrderDetailService;
import com.tsd.jxc.buy.service.JxcBuyOrderService;
import com.tsd.jxc.buy.service.JxcBuyReturnBillService;
import com.tsd.jxc.buy.vo.JxcBuyStockInfoVo;
import com.tsd.jxc.config.JxcCodeRuleConstants;
import com.tsd.jxc.fin.FinanceConstants;
import com.tsd.jxc.fin.dao.JxcFinanceAccountDetailMapper;
import com.tsd.jxc.fin.dao.JxcFinanceAccountMapper;
import com.tsd.jxc.fin.entity.JxcFinanceAccountDetailExt;
import com.tsd.jxc.fin.entity.JxcFinanceAccountExt;
import com.tsd.jxc.fin.job.JxcFinanceJob;
import com.tsd.jxc.goods.entity.JxcGoodsPriceExt;
import com.tsd.jxc.goods.service.JxcGoodsPriceService;
import com.tsd.jxc.order.entity.JxcOrderAmountDetailExt;
import com.tsd.jxc.order.service.JxcOrderAmountDetailService;
import com.tsd.jxc.sale.dao.JxcSaleOrderDetailMapper;
import com.tsd.jxc.sale.dao.JxcSaleOrderMapper;
import com.tsd.jxc.sale.entity.JxcSaleOrderDetailExt;
import com.tsd.jxc.sale.service.JxcSaleOrderDetailService;
import com.tsd.jxc.sale.service.JxcSaleOrderService;
import com.tsd.jxc.setting.JxcSettingUtil;
import com.tsd.jxc.stock.StockConstants;
import com.tsd.jxc.stock.entity.JxcStockInbillExt;
import com.tsd.jxc.stock.service.JxcStockGoodsService;
import com.tsd.jxc.stock.service.JxcStockInbillService;
import com.tsd.jxc.vo.JxcSettingVo;
import com.tsd.service.BaseServiceImpl;
import com.tsd.system.entity.SysUser;
import com.tsd.system.entity.SysUserExt;
import com.tsd.system.service.SystemSettingService;
import com.tsd.system.vo.GlobalSetting;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 描述：JxcBuyOrder 服务实现层
 *
 * @author Hillpool
 * @date 2022/07/29 15:00:45
 */
@Service
public class JxcBuyOrderServiceImpl extends BaseServiceImpl implements JxcBuyOrderService, GetDuplicatedObj {

    @Resource
    private JxcBuyOrderMapper jxcBuyOrderMapper;
    @Resource
    private JxcBuyOrderDetailMapper jxcBuyOrderDetailMapper;
    @Resource
    private JxcOrderAmountDetailService jxcOrderAmountDetailService;
    @Resource
    private JxcSaleOrderDetailMapper jxcSaleOrderDetailMapper;
    @Resource
    private JxcSaleOrderMapper jxcSaleOrderMapper;
    @Resource
    private JxcBuyOrderDetailSodMapper jxcBuyOrderDetailSodMapper;
    @Resource
    private BaseCodeRuleService baseCodeRuleService;
    @Resource
    private JxcBuyOrderDetailService jxcBuyOrderDetailService;
    @Resource
    private JxcSaleOrderDetailService jxcSaleOrderDetailService;
    @Lazy
    @Resource
    private JxcSaleOrderService jxcSaleOrderService;
    @Resource
    private JxcBuyReturnBillService jxcBuyReturnBillService;
    @Resource
    private JxcStockInbillService jxcStockInbillService;
    @Resource
    private JxcFinanceAccountMapper jxcFinanceAccountMapper;
    @Resource
    private JxcFinanceAccountDetailMapper jxcFinanceAccountDetailMapper;
    @Resource
    private JxcFinanceJob jxcFinanceJob;
    @Resource
    private BaseInvoiceInfoService baseInvoiceInfoService;
    @Resource
    private SystemSettingService systemSettingService;
    @Resource
    private JxcStockGoodsService jxcStockGoodsService;
    @Resource
    private JxcGoodsPriceService jxcGoodsPriceService;

    @Override
    public JxcBuyOrder getJxcBuyOrderById(Long id) throws Exception {
        return jxcBuyOrderMapper.selectByPrimaryKey(id);
    }

    @Override
    public JxcBuyOrderExt queryBySid(String sid) throws Exception {
        JxcBuyOrderExt orderExt = jxcBuyOrderMapper.selectBySid(sid);
        if (orderExt != null) {
            List<JxcBuyOrderDetailExt> detailExtList = jxcBuyOrderDetailService.queryValidByOrderList(Collections.singletonList(orderExt.getSid()));
            orderExt.setDetail_list(detailExtList);
        }
        return orderExt;
    }

    private void checkReturn(List<String> list, Integer state) throws Exception {
        List<JxcBuyOrderExt> checkList = jxcBuyOrderMapper.selectValid4Return(list);
        List<JxcBuyOrderExt> filterList = ListUtil.filter(checkList, t -> !HlpUtils.isEmpty(t.getQty()) && t.getQty().doubleValue() > 0);
        if (!HlpUtils.isEmptyList(filterList)) {
            List<String> codeList = ListUtil.map(filterList, JxcBuyOrderExt::getCode);
            String msg = "采购订单：" + StringUtils.join(codeList, "、") + " 已生成退货单，";
            if (!HlpUtils.isEmpty(state)) {
                msg += "无法" + (state == 1 ? "审核" : "反审") + "！";
            } else {
                msg += "无法删除！";
            }
            throw new HlpException(msg);
        }
    }

    @Override
    public void deleteJxcBuyOrders(List<String> list, SysUser opUser) throws Exception {
        if (HlpUtils.isEmptyList(list)) {
            return;
        }

        JxcBuyOrderExt params = new JxcBuyOrderExt();
        params.setDr(0);
        params.setSid_list(list);
        List<JxcBuyOrderExt> orderExtList = jxcBuyOrderMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(orderExtList)) {
            throw new HlpException("订单信息为空");
        }
        // 检查采购订单是否已对账
        List<JxcBuyOrderExt> filterPayReqList = ListUtil.filter(orderExtList, t -> !HlpUtils.isEmpty(t.getPay_req_state()) && Constants.VALUE_NO != t.getPay_req_state());
        if (!HlpUtils.isEmptyList(filterPayReqList)) {
            List<String> codeList = ListUtil.map(filterPayReqList, JxcBuyOrderExt::getCode);
            String msg = "采购订单：" + StringUtils.join(codeList, "、") + " 已对账，无法删除";
            throw new HlpException(msg);
        }

        // 检查采购订单是否已生成退货单
        this.checkReturn(list, null);

        BatchDeleteLogicVo logicVo = new BatchDeleteLogicVo(opUser);
        logicVo.setSidList(list);
        jxcBuyOrderMapper.deleteLogicBySidList(logicVo);

        jxcBuyOrderDetailMapper.deleteLogicByOrderList(logicVo);

        // 删除以销定购关联数据
        jxcBuyOrderDetailSodMapper.deleteLogicByBuyOrderList(logicVo);
        // 计算货品平均成本
//        ThreadPoolTaskUtil.executeInList4Split(list, false, itemList -> jxcGoodsProductMapper.updateInfoByBuyOrderAudit(itemList, -1));
//        if (!list.isEmpty()) {
//            jxcOrderAmountDetailService.deleteJxcOrderAmountDetailsByOrderSid(list, opUser);
//        }
    }

    @Override
    public boolean isDuplicated(Object obj, String code) {
        if (obj == null) {
            return false;
        }
        JxcBuyOrderExt orderExt = (JxcBuyOrderExt) obj;
        orderExt.setCode(code);
        return jxcBuyOrderMapper.selectDuplicatedCode(orderExt) != null;
    }

    @Override
    @GenSnQue(ruleCode = JxcCodeRuleConstants.TYPE_JXC_BUY_ORDER, clientFieldName = "", supplierFieldName = "supplier_sid")
    public void saveJxcBuyOrder(JxcBuyOrderExt record, SysUser opUser) throws Exception {
        if (HlpUtils.isEmpty(record.getId())) {
            if (!HlpUtils.isEmpty(record.getCode())) {
                //如果是手动设置了编号，则检查是否有相同的，有的话，置空后重新生成
                JxcBuyOrderExt same = jxcBuyOrderMapper.selectDuplicatedCode(record);
                if (same != null) {
                    record.setCode(null);
                }
            }
            String genCode = baseCodeRuleService.genCode(record.getSupplier_sid(), JxcCodeRuleConstants.TYPE_JXC_BUY_ORDER, JxcCodeRuleConstants.TYPE_NAME_JXC_BUY_ORDER, opUser, record.getCode(), record, this);
            record.setCode(genCode);
            record.setAudit_state(Constants.VALUE_NO);
            record.setState(Constants.VALUE_YES);
            super.autoInjectBaseData(record, opUser, this.TYPE_CREATE, new Date(), record.getOrder_date());
            jxcBuyOrderMapper.insertSelective(record);
            jxcBuyOrderDetailService.saveJxcBuyOrderDetail(record, true, opUser);
            // 生成收付款明细
//            this.genOrderAmountDetail(record, opUser);
        } else {
            JxcBuyOrderExt same = jxcBuyOrderMapper.selectDuplicatedCode(record);
            if (same != null) {
                throw new HlpException("已存在相同编号的订单");
            }
            super.autoInjectBaseData(record, opUser, this.TYPE_UPDATE);
            super.updateYyyyMmdd(record, record.getOrder_date());
            jxcBuyOrderMapper.updateByPrimaryKeySelective(record);
            jxcBuyOrderDetailService.saveJxcBuyOrderDetail(record, true, opUser);
        }
    }

    private void genOrderAmountDetail(JxcBuyOrderExt record, SysUser opUser) throws Exception {
        if (!HlpUtils.isEmpty(record.getPaid_amount()) && record.getPaid_amount().doubleValue() > 0) {
            JxcOrderAmountDetailExt detailExt = new JxcOrderAmountDetailExt();
            detailExt.setType(StockConstants.PAY_TYPE_FOR_BUY);
            detailExt.setThe_date(new Date());
            detailExt.setOrder_sid(record.getSid());
            detailExt.setAmount(record.getPaid_amount());
            detailExt.setRemain_amount(record.getUn_pay_amount());
            detailExt.setPay_type(record.getPay_type());
            jxcOrderAmountDetailService.saveJxcOrderAmountDetail(detailExt, opUser);
        }
    }

    @Override
    public List<JxcBuyOrderExt> findJxcBuyOrders(Map<String, Object> params, PageBean page) throws Exception {
        List<JxcBuyOrderExt> list = jxcBuyOrderMapper.selectByPage(params, page);
        String goods_name = HlpUtils.getString(params, "goods_name");
        Integer export_excel = HlpUtils.getInteger(params, "export_excel");
        if (!HlpUtils.isEmptyList(list) && (!HlpUtils.isEmpty(goods_name) || !HlpUtils.isEmpty(export_excel))) {
            List<String> orderList = ListUtil.map(list, JxcBuyOrderExt::getSid);
            JxcBuyOrderDetailExt detailParams = new JxcBuyOrderDetailExt();
            detailParams.setDr(0);
            detailParams.setOrder_list(orderList);
            if (!HlpUtils.isEmpty(goods_name)) {
                detailParams.setGoods_name(goods_name);
            }
            List<JxcBuyOrderDetailExt> detailExtList = jxcBuyOrderDetailMapper.selectByEntity(detailParams);
            for (JxcBuyOrderExt orderExt : list) {
                List<JxcBuyOrderDetailExt> filterList = ListUtil.filter(detailExtList, t -> t.getOrder_sid().equals(orderExt.getSid()));
                orderExt.setDetail_list(filterList);
            }
        }
        return list;
    }

    @Override
    public List<JxcBuyOrderExt> findJxcBuyOrders(Map<String, Object> params) throws Exception {
        return jxcBuyOrderMapper.selectByParams(params);
    }

    @Override
    public void changeJxcBuyOrderAuditState(List<String> sidList, Integer state, SysUserExt opUser) throws Exception {
        JxcBuyOrderExt params = new JxcBuyOrderExt();
        params.setDr(0);
        params.setSid_list(sidList);
        List<JxcBuyOrderExt> orderExtList = jxcBuyOrderMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(orderExtList)) {
            throw new HlpException("订单信息为空");
        }
        // 检查采购订单是否已对账
        List<JxcBuyOrderExt> filterPayReqList = ListUtil.filter(orderExtList, t -> !HlpUtils.isEmpty(t.getPay_req_state()) && Constants.VALUE_NO != t.getPay_req_state());
        if (!HlpUtils.isEmptyList(filterPayReqList)) {
            List<String> codeList = ListUtil.map(filterPayReqList, JxcBuyOrderExt::getCode);
            String msg = "采购订单：" + StringUtils.join(codeList, "、") + " 已对账，无法" + (state == 1 ? "审核" : "反审");
            throw new HlpException(msg);
        }
        // 检查采购订单是否已生成退货单
        this.checkReturn(sidList, state);

        boolean isFree = VersionConstants.accountSetVersionIsFree();
        //免费版本，销售订单、采购订单、销售退货、采购退货审核后更新库存
        for (JxcBuyOrderExt orderExt : orderExtList) {
            if (state == 1) {
                orderExt.setAudit_state(Constants.VALUE_YES);
                orderExt.setAuditor_sid(opUser.getSid());
                orderExt.setAuditor_name(opUser.getName());
                orderExt.setAudit_date(new Date());
                if (isFree) {
                    jxcStockGoodsService.updateByBuyOrder(Constants.OP_ADD, orderExt);
                }
            } else if (state == -1) {
                orderExt.setAudit_state(Constants.VALUE_NO);
                orderExt.setAuditor_sid(null);
                orderExt.setAuditor_name(null);
                orderExt.setAudit_date(null);
                if (isFree) {
                    jxcStockGoodsService.updateByBuyOrder(Constants.OP_SUB, orderExt);
                }
            }
            jxcBuyOrderMapper.updateByPrimaryKey(orderExt);
        }

        List<String> orderList = ListUtil.map(orderExtList, JxcBuyOrderExt::getSid);
        ThreadPoolTaskUtil.executeInList4Split(orderList, false, itemList -> jxcBuyOrderDetailMapper.updateStockQty4BuyAudit(itemList));
    }

    @Override
    public void cancelJxcBuyOrder(List<String> sidList, SysUserExt opUser) throws Exception {
        JxcBuyOrderExt params = new JxcBuyOrderExt();
        params.setDr(0);
        params.setSid_list(sidList);
        List<JxcBuyOrderExt> orderExtList = jxcBuyOrderMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(orderExtList)) {
            return;
        }

        List<JxcBuyOrderExt> filterList = ListUtil.filter(orderExtList, t -> Constants.VALUE_NO == t.getState());
        if (!HlpUtils.isEmptyList(filterList)) {
            List<String> codeList = ListUtil.map(filterList, JxcBuyOrderExt::getCode);
            throw new HlpException("采购单：" + StringUtils.join(codeList, "、") + " 已作废");
        }

        // 检查是否有销售单
        List<String> orderList = ListUtil.map(orderExtList, JxcBuyOrderExt::getSid);
        List<JxcBuyOrderExt> checkList = jxcBuyOrderMapper.select4CheckSale(orderList);
        if (!HlpUtils.isEmptyList(checkList)) {
            JxcBuyOrderExt orderExt = ListUtil.get(orderExtList, t -> t.getSid().equals(checkList.get(0).getSid()));
            if (orderExt != null) {
                throw new HlpException("采购单：" + orderExt.getCode() + " 已存在销售单：" + checkList.get(0).getCode() + " 无法作废");
            }
        }

        List<JxcBuyOrderExt> updateList = new ArrayList<>();
        for (JxcBuyOrderExt orderExt : orderExtList) {
            orderExt.setState(Constants.VALUE_NO);
            updateList.add(orderExt);
        }
        if (!HlpUtils.isEmptyList(updateList)) {
            ThreadPoolTaskUtil.executeInList4Split(updateList, false, itemList -> jxcBuyOrderMapper.updateList(itemList));
            List<String> orderSidList = ListUtil.map(updateList, JxcBuyOrderExt::getSid);
            if (!HlpUtils.isEmptyList(orderSidList)) {
                jxcOrderAmountDetailService.cancelJxcOrderAmountDetailsByOrderSid(orderSidList, opUser);
            }
        }
    }

    private List<JxcBuyOrderExt> queryBySidList(List<String> sidList) {
        List<JxcBuyOrderExt> orderExtList = ThreadPoolTaskUtil.queryInList4Split(sidList, list -> {
            JxcBuyOrderExt params = new JxcBuyOrderExt();
            params.setDr(0);
            params.setSid_list(list);
            return jxcBuyOrderMapper.selectByEntity(params);
        });
        if (HlpUtils.isEmptyList(orderExtList)) {
            return null;
        }
        List<String> orderList = ListUtil.map(orderExtList, JxcBuyOrderExt::getSid);
        List<JxcBuyOrderDetailExt> detailExtList = ThreadPoolTaskUtil.queryInList4Split(orderList, list -> jxcBuyOrderDetailService.queryValidByOrderList(list));
        if (HlpUtils.isEmptyList(detailExtList)) {
            return null;
        }
        for (JxcBuyOrderExt orderExt : orderExtList) {
            List<JxcBuyOrderDetailExt> filterList = ListUtil.filter(detailExtList, t -> t.getOrder_sid().equals(orderExt.getSid()));
            if (HlpUtils.isEmptyList(filterList)) {
                continue;
            }
            orderExt.setDetail_list(filterList);
        }
        return ListUtil.filter(orderExtList, t -> !HlpUtils.isEmptyList(t.getDetail_list()));
    }

    @Override
    public int genJxcBuyOrder2InBill(List<String> sidList, SysUserExt opUser) throws Exception {
        List<JxcBuyOrderExt> orderExtList = this.queryBySidList(sidList);
        orderExtList = ListUtil.filter(orderExtList, t -> !StockConstants.IN_OUT_BILL_ALL.equals(t.getIn_bill()));
        if (HlpUtils.isEmptyList(orderExtList)) {
            return 0;
        }
        int qty=0;
        List<String> srcList = new ArrayList<>();
        for (JxcBuyOrderExt orderExt : orderExtList) {
            List<JxcStockInbillExt> inbillExtList = orderExt.genInBill4Supplier(null);
            if (HlpUtils.isEmptyList(inbillExtList)) {
                continue;
            }
            for (JxcStockInbillExt inBillExt : inbillExtList) {
                if (HlpUtils.isEmptyList(inBillExt.getItem_list())) {
                    continue;
                }
                jxcStockInbillService.saveJxcStockInbill(inBillExt, opUser);
                qty++;
                List<JxcBuyOrderDetailExt> detailExtList = ListUtil.filter(orderExt.getDetail_list(), t -> inBillExt.getSupplier_sid().equals(t.getSupplier_sid()));
                for (JxcBuyOrderDetailExt detailExt : detailExtList) {
                    srcList.add(detailExt.getSid());
                }
            }
        }
        if (!HlpUtils.isEmptyList(srcList)) {
            jxcBuyOrderDetailMapper.updateInQty(srcList);
        }
        if (!HlpUtils.isEmptyList(sidList)) {
            jxcBuyOrderMapper.updateInBill(sidList);
        }
        return qty;
    }

    @Override
    public void genJxcBuyOrder2ReturnBill(List<String> sidList, SysUserExt opUser) throws Exception {
        List<JxcBuyOrderExt> orderExtList = this.queryBySidList(sidList);
        if (HlpUtils.isEmptyList(orderExtList)) {
            return;
        }
        List<JxcBuyOrderDetailExt> detailExtList = new ArrayList<>();
        for (JxcBuyOrderExt orderExt : orderExtList) {
            detailExtList.addAll(orderExt.getDetail_list());
        }
        List<String> supplierList = ListUtil.map(detailExtList, JxcBuyOrderDetailExt::getSupplier_sid);
        for (String supplierSid : supplierList) {
            List<JxcBuyOrderDetailExt> filterDetailList = ListUtil.filter(detailExtList, t -> t.getSupplier_sid().equals(supplierSid));
            if (HlpUtils.isEmptyList(filterDetailList)) {
                continue;
            }
            JxcBuyOrderExt orderExt = new JxcBuyOrderExt();
            orderExt.setSupplier_sid(supplierSid);
            orderExt.setSupplier_name_join(filterDetailList.get(0).getSupplier_name());
            orderExt.setSupplier_code(filterDetailList.get(0).getSupplier_code());
            orderExt.setSupplier_short_name(filterDetailList.get(0).getSupplier_short_name());
            orderExt.setSupplier_contact_name(filterDetailList.get(0).getSupplier_contact_name());
            orderExt.setSupplier_contact_phone(filterDetailList.get(0).getSupplier_contact_phone());
            orderExt.setDetail_list(filterDetailList);

            JxcBuyReturnBillExt billExt = orderExt.genReturnBill();
            if (HlpUtils.isEmptyList(billExt.getDetail_list())) {
                continue;
            }
            jxcBuyReturnBillService.saveJxcBuyReturnBill(billExt, opUser);
        }
    }

    @Override
    public JxcBuyReturnBillExt getJxcBuyOrder2ReturnBillData(String sid) throws Exception {
        JxcBuyOrderExt orderExt = this.queryBySid(sid);
        super.checkEmpty(orderExt, "采购订单不存在");
        return orderExt.genReturnBill();
    }

    @Override
    public Integer genJxcFinanceAccountDetail4Buy(List<String> sidList, SysUserExt opUser) throws Exception {
        JxcBuyOrderExt params = new JxcBuyOrderExt();
        params.setDr(0);
        params.setSid_list(sidList);
        List<JxcBuyOrderExt> orderExtList = jxcBuyOrderMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(orderExtList)) {
            return 0;
        }
        List<JxcBuyOrderExt> filterList = ListUtil.filter(orderExtList, t -> !HlpUtils.isEmpty(t.getGen_finance()) && t.getGen_finance() == 1);
        if (!HlpUtils.isEmptyList(filterList)) {
            List<String> codeList = ListUtil.map(orderExtList, JxcBuyOrderExt::getCode);
            throw new HlpException("采购订单：" + StringUtils.join(codeList, "、") + " 已生成对账！");
        }

        List<String> supplierList = ListUtil.map(orderExtList, JxcBuyOrderExt::getSupplier_sid);
        // 查询账户余额
        List<JxcFinanceAccountExt> accountExtList = jxcFinanceAccountMapper.selectValidByPartyList(supplierList);
        Map<String, Double> remainAmountMap = new HashMap<>();
        orderExtList = ListUtil.sorted(orderExtList, Comparator.comparing(JxcBuyOrderExt::getId));
        List<JxcBuyOrderExt> updateList = new ArrayList<>();
        List<JxcFinanceAccountDetailExt> list = new ArrayList<>();
        String dataSource = DataSourceContextHolder.getDataSourceType();
        for (JxcBuyOrderExt orderExt : orderExtList) {
            JxcFinanceAccountExt accountExt = ListUtil.get(accountExtList, t -> t.getRelated_party_sid().equals(orderExt.getSupplier_sid()));
            List<JxcFinanceAccountDetailExt> detailExtList = orderExt.genAccountDetail();
            if (!HlpUtils.isEmptyList(detailExtList)) {
                for (JxcFinanceAccountDetailExt detailExt : detailExtList) {
                    super.autoInjectBaseData(detailExt, opUser, this.TYPE_CREATE);
                    double remainAmount = 0D;
                    if (remainAmountMap.containsKey(orderExt.getSupplier_sid())) {
                        remainAmount = remainAmountMap.get(orderExt.getSupplier_sid());
                    } else if (accountExt != null) {
                        remainAmount = accountExt.getAmount().doubleValue();
                    }
                    if (FinanceConstants.OP_ADD.equals(FinanceConstants.getAccountTypeOp(dataSource, detailExt.getBill_type()))) {
                        remainAmount = DoubleUtil.add(remainAmount, FinanceConstants.getAmount(detailExt));
                    } else {
                        remainAmount = DoubleUtil.sub(remainAmount, FinanceConstants.getAmount(detailExt));
                    }
                    remainAmountMap.put(orderExt.getSupplier_sid(), remainAmount);
                    detailExt.setRemain_amount(BigDecimal.valueOf(remainAmount));
                    String genCode = baseCodeRuleService.genCode(orderExt.getSupplier_sid(), JxcCodeRuleConstants.TYPE_JXC_FINANCE_ACCOUNT, JxcCodeRuleConstants.TYPE_NAME_JXC_FINANCE_ACCOUNT, opUser, null, null, null);
                    detailExt.setCode(genCode);
                    list.add(detailExt);
                }
            }

            JxcBuyOrderExt updateData = new JxcBuyOrderExt();
            updateData.setId(orderExt.getId());
            updateData.setSid(orderExt.getSid());
            updateData.setGen_finance(1);
            super.autoInjectBaseData(updateData, opUser, this.TYPE_UPDATE);
            updateList.add(updateData);
        }

        ThreadPoolTaskUtil.executeInList4Split(list, false, itemList -> jxcFinanceAccountDetailMapper.insertList(itemList));

        // 更新字段：gen_finance
        ThreadPoolTaskUtil.executeInList4Split(updateList, false, itemList -> jxcBuyOrderMapper.updateList(itemList));

        // 添加队列
        for (JxcFinanceAccountDetailExt detailExt : list) {
            jxcFinanceJob.addJxcFinanceQue(FinanceConstants.QUEUE_OP_INSERT, FinanceConstants.BIZ_NAME_FINANCE, "updateFinanceAmount", detailExt.getId(), opUser);
        }
        return list.size();
    }

    @Override
    public List<JxcBuyOrderExt> findJxcBuyOrdersIncludeDetail(Map<String, Object> params, PageBean page) {
        return jxcBuyOrderMapper.selectBuyOrdersIncludeDetailByPage(params, page);
    }

    @Override
    public List<JxcBuyOrderExt> queryJxcBuyOrderData4Print(List<String> sidList) throws Exception {
        List<JxcBuyOrderExt> list = ThreadPoolTaskUtil.queryInList4Split(sidList, itemList -> {
            JxcBuyOrderExt params = new JxcBuyOrderExt();
            params.setDr(0);
            params.setSid_list(itemList);
            return jxcBuyOrderMapper.selectByEntity(params);
        });
        if (!HlpUtils.isEmptyList(list)) {
            List<String> orderList = ListUtil.map(list, JxcBuyOrderExt::getSid);
            List<JxcBuyOrderDetailExt> detailExtList = jxcBuyOrderDetailService.queryValidByOrderList(orderList);
            for (JxcBuyOrderExt orderExt : list) {
                List<JxcBuyOrderDetailExt> filterList = ListUtil.filter(detailExtList, t -> t.getOrder_sid().equals(orderExt.getSid()));
                orderExt.setDetail_list(filterList);
            }
        }
        return list;
    }

    @Override
    public List<JxcBuyStockInfoVo> findJxcBuyOrders4Stock(Map<String, Object> params, PageBean page) throws Exception {
        return jxcBuyOrderMapper.select4StockByPage(params, page);
    }

    @Override
    public List<JxcBuyOrderExt> findJxcBuyOrders4Select(Map<String, Object> params, PageBean page) throws Exception {
        List<JxcBuyOrderExt> list = jxcBuyOrderMapper.select4SelectByPage(params, page);
        if (!HlpUtils.isEmptyList(list)) {
            String saleOrderSid = HlpUtils.getString(params, "sale_order_sid");
            List<JxcSaleOrderDetailExt> saleOrderDetailExtList = null;
            if (!HlpUtils.isEmpty(saleOrderSid)) {
                saleOrderDetailExtList = jxcSaleOrderDetailService.queryValidByOrderList(Collections.singletonList(saleOrderSid));
            }
            List<String> orderList = ListUtil.map(list, JxcBuyOrderExt::getSid);
            List<JxcBuyOrderDetailExt> detailExtList = jxcBuyOrderDetailService.queryValidByOrderList(orderList);
            if (!HlpUtils.isEmptyList(detailExtList)) {
                for (JxcBuyOrderExt orderExt : list) {
                    List<JxcBuyOrderDetailExt> filterList = ListUtil.filter(detailExtList, t -> t.getOrder_sid().equals(orderExt.getSid()));
                    for (JxcBuyOrderDetailExt detailExt : filterList) {
                        double stockQty = DoubleUtil.sub(detailExt.getQty4base(), detailExt.getQty4base());
                        JxcSaleOrderDetailExt saleOrderDetailExt = ListUtil.get(saleOrderDetailExtList, t -> detailExt.getSid().equals(t.getBuy_order_detail_sid()));
                        if (saleOrderDetailExt != null) {
                            stockQty = DoubleUtil.add(stockQty, saleOrderDetailExt.getQty());
                        }
//                        detailExt.setStock_qty(BigDecimal.valueOf(stockQty));
                    }
//                    filterList = ListUtil.filter(filterList, t -> t.getStock_qty().doubleValue() > 0);
//                    orderExt.setDetail_list(filterList);
//                    double stockQty = ListUtil.sum(filterList, t -> t.getStock_qty().doubleValue());
//                    orderExt.setStock_qty(BigDecimal.valueOf(stockQty));
//                    double stockAmount = ListUtil.sum(filterList, t -> DoubleUtil.mul(t.getPrice(), t.getStock_qty()));
//                    orderExt.setStock_amount(BigDecimal.valueOf(stockAmount));
                }
            }
        }
        return list;
    }

    @Override
    public void importJxcBuyOrder(JxcBuyOrderExt orderExt, SysUserExt opUser) throws Exception {
        super.checkEmpty(orderExt.getSupplier_sid(), "请提供参数：supplier_sid");
        super.checkEmptyList(orderExt.getDetail_list(), "明细不能为空");
        if (orderExt.getId() == null) {
            String genCode = baseCodeRuleService.genCode(orderExt.getSupplier_sid(), JxcCodeRuleConstants.TYPE_JXC_BUY_ORDER, JxcCodeRuleConstants.TYPE_NAME_JXC_BUY_ORDER, opUser, orderExt.getCode(), orderExt, this);
            orderExt.setCode(genCode);
            orderExt.setAudit_state(Constants.VALUE_NO);
            orderExt.setState(Constants.VALUE_YES);
            super.autoInjectBaseData(orderExt, opUser, this.TYPE_CREATE, new Date(), orderExt.getOrder_date());
            jxcBuyOrderMapper.insertSelective(orderExt);
        }
        List<JxcBuyOrderDetailExt> detailExtList = orderExt.getDetail_list();
        List<String> goodsSpecList = ListUtil.map(detailExtList, t -> String.format("%s-%s", t.getGoods_name(), t.getSpec_info()));
//        JxcGoodsProductExt params = new JxcGoodsProductExt();
//        params.setDr(0);
//        params.setOwner_sid(orderExt.getSupplier_sid());
//        params.setGoods_spec_list(goodsSpecList);
//        List<JxcGoodsProductExt> productExtList = jxcGoodsProductMapper.selectByEntity(params);
//        List<JxcGoodsProductExt> insertList = new ArrayList<>();
//        for (JxcBuyOrderDetailExt detailExt : detailExtList) {
//            JxcGoodsProductExt productExt = ListUtil.get(productExtList, t -> t.getName().equals(detailExt.getGoods_name()) && t.getSpec_info().equals(detailExt.getSpec_info()));
//            if (productExt == null) {
//                productExt = new JxcGoodsProductExt();
//                productExt.setName(detailExt.getGoods_name());
//                productExt.setSpec_info(detailExt.getSpec_info());
//                productExt.setUnit(detailExt.getUnit());
//                productExt.setQty(0);
//                productExt.setPrice(BigDecimal.ZERO);
//                productExt.setBuy_cost(detailExt.getPrice());
//                productExt.setGoods_sid("0");
//                productExt.setSpecifications("[]");
//                productExt.setOwner_sid(orderExt.getSupplier_sid());
//                super.autoInjectBaseData(productExt, opUser, this.TYPE_CREATE);
//                insertList.add(productExt);
//            }
//            detailExt.setSupplier_sid(orderExt.getSupplier_sid());
//            detailExt.setProduct_sid(productExt.getSid());
//        }
//        orderExt.setDetail_list(detailExtList);
//        if (!HlpUtils.isEmptyList(insertList)) {
//            ThreadPoolTaskUtil.executeInList4Split(insertList, false, itemList -> jxcGoodsProductMapper.insertList(itemList));
//        }
        jxcBuyOrderDetailService.saveJxcBuyOrderDetail(orderExt, false, opUser);
    }

    private String getUnionKeySale2Buy(JxcSaleOrderDetailExt detailExt) {
        return String.format("%s_%s", detailExt.getGoods_sid(), detailExt.getUnit_name());
    }

    private String getUnionKeySale2Buy(JxcBuyOrderDetailExt detailExt) {
        return String.format("%s_%s", detailExt.getGoods_sid(), detailExt.getUnit_name());
    }

    private String getUnionKeySale2Buy(JxcGoodsPriceExt priceExt) {
        return String.format("%s_%s", priceExt.getGoods_sid(), priceExt.getUnit_name());
    }

    @Override
    public JxcBuyOrderExt getJxcSale2BuyData(List<String> saleOrderList, List<String> saleOrderDetailList) throws Exception {
        if (HlpUtils.isEmptyList(saleOrderList) && HlpUtils.isEmptyList(saleOrderDetailList)) {
            throw new HlpException("请选择数据");
        }
        List<JxcSaleOrderDetailExt> list = jxcSaleOrderDetailMapper.select4Sale2Buy(saleOrderList, saleOrderDetailList);
        if (HlpUtils.isEmptyList(list)) {
            throw new HlpException("空数据");
        }
        List<JxcBuyOrderDetailExt> existList = jxcBuyOrderDetailMapper.selectExist4Sale2Buy(saleOrderList, saleOrderDetailList);
        List<String> goodsList = ListUtil.map(list, JxcSaleOrderDetailExt::getGoods_sid);
        List<JxcGoodsPriceExt> priceExtList = jxcGoodsPriceService.queryByGoodsList(goodsList);
        JxcBuyOrderExt orderExt = new JxcBuyOrderExt();
        JxcSettingVo settingVo = JxcSettingUtil.getSettingVo();
        if (!HlpUtils.isEmptyList(list)) {
            List<JxcBuyOrderDetailExt> detailExtList = new ArrayList<>();
            for (JxcSaleOrderDetailExt saleOrderDetailExt : list) {
                JxcGoodsPriceExt priceExt = ListUtil.get(priceExtList, t -> this.getUnionKeySale2Buy(saleOrderDetailExt).equals(this.getUnionKeySale2Buy(t)));
                if (priceExt == null) {
                    continue;
                }
                JxcBuyOrderDetailExt detailExt = saleOrderDetailExt.genBuyOrderDetail();
                detailExt.setPrice_list(ListUtil.filter(priceExtList, t -> t.getGoods_sid().equals(saleOrderDetailExt.getGoods_sid())));
                detailExt.setUnit_qty(BigDecimal.valueOf(priceExt.getQty()));
                detailExt.setTax_rate(settingVo.getDefault_tax_ratio());
                JxcBuyOrderDetailExt existExt = ListUtil.get(existList, t -> this.getUnionKeySale2Buy(t).equals(this.getUnionKeySale2Buy(saleOrderDetailExt)));
                if (existExt != null) {
                    detailExt.setGen_bill_num(existExt.getGen_bill_num());
                    detailExt.setGen_buy_qty(existExt.getQty());
                    detailExt.setGen_buy_qty4base(existExt.getQty4base());
                }
                detailExt.setSale_req_qty(BigDecimal.valueOf(DoubleUtil.sub(detailExt.getQty(), detailExt.getGen_buy_qty())));
                detailExt.setSale_req_qty4base(BigDecimal.valueOf(DoubleUtil.sub(detailExt.getQty4base(), detailExt.getGen_buy_qty4base())));
                if (detailExt.getSale_req_qty4base().doubleValue() <= 0) {
                    continue;
                }
                detailExt.setQty(detailExt.getSale_req_qty());
                detailExt.setQty4base(detailExt.getSale_req_qty4base());
                detailExt.setPrice(priceExt.getBuy_price());
                detailExt.setList_price(detailExt.getPrice());
                double amount = DoubleUtil.mul(detailExt.getPrice(), detailExt.getQty());
                detailExt.setAmount(BigDecimal.valueOf(amount));
                detailExt.calc(null, settingVo, true);
                detailExtList.add(detailExt);
            }
            orderExt.setDetail_list(detailExtList);

        }
        orderExt.setOrder_date(new Date());
        return orderExt;
    }

    @Override
    public List<String> saveJxcBuyOrder4Sale2Buy(JxcBuyOrderExt orderExt, JxcSettingVo settingVo, SysUserExt opUser) throws Exception {
        super.checkEmptyList(orderExt.getDetail_list(), "采购单明细不能为空");
        List<String> orderList = new ArrayList<>();
        if (JxcSettingVo.STATE_DISABLE == settingVo.getBuy_order_only_one_supplier()) {
            this.saveJxcBuyOrder(orderExt, opUser);
            orderList.add(orderExt.getSid());
        } else {
            List<JxcBuyOrderDetailExt> detailExtList = orderExt.getDetail_list();
            for (JxcBuyOrderDetailExt detailExt : detailExtList) {
                super.checkEmpty(detailExt.getSupplier_sid(), "序号：" + detailExt.getSn() + " 供应商不能为空");
            }
            List<String> unionSupplierList = ListUtil.map(detailExtList, JxcBuyOrderDetailExt::getSupplier_sid);
            for (String supplierSid : unionSupplierList) {
                List<JxcBuyOrderDetailExt> filterList = ListUtil.filter(detailExtList, t -> supplierSid.equals(t.getSupplier_sid()));
                if (HlpUtils.isEmptyList(filterList)) {
                    continue;
                }
                JxcBuyOrderExt buyOrderExt = orderExt.copy();
                buyOrderExt.setDetail_list(filterList);
                buyOrderExt.setSupplier_sid(supplierSid);
                this.saveJxcBuyOrder(buyOrderExt, opUser);
                orderList.add(buyOrderExt.getSid());
            }
        }
        return orderList;
    }

}
